<?
##########################################################################
#		DOCUMENTATION
##########################################################################
# Class that extends the core class. This module will provide the methods
# needed by the site to access books' informations.
#
# © LiberLab group, 2011
##########################################################################

require_once("core.php");

class Book extends Core{
	private $queryBasic = "SELECT id, title, views, pubblicationData, coverExtension FROM books ORDER BY __order__ DESC LIMIT :limit";
	public function __construct() {
		parent::__construct();
	}
	
	public function exists($title, $category, $authors){
		# check the existance of a book in the DB
		# database is static
		$database = self::$database;
		$query = "SELECT b.id FROM books b JOIN booksAuthors ba ON b.id=ba.bookId JOIN authors a ON ba.authorId = a.id JOIN booksCategories bc ON b.id=bc.bookId JOIN categories c ON bc.categoryId = c.id WHERE b.title= :title AND c.name= :category";	

		if ($authors){
			# expand "author1, author2, ecc." in an array
			$authors = explode(", ", $authors);
			$query = $query . " AND (";
			# to do the magic, make the query using concat (avoid problems)
			for($index = 0; $index < count($authors); $index++){
				$author = $authors[$index];	
				if ($index == 0){
					$query = $query . "(CONCAT(a.name, \" \", a.surname) =  :author$index)"; 	
				}else{
					$query = $query . " OR (CONCAT(a.name, \" \", a.surname) =  :author$index)";
				}
			}
			$query = $query . ")";
			$stpdo = $database->getStpdo($query);
			for($index = 0; $index < count($authors); $index++){
				$stpdo->bindParam(":author$index", $authors[$index], PDO::PARAM_STR); 
			}
		}
		$stpdo->bindParam(':title', $title, PDO::PARAM_STR); 
		$stpdo->bindParam(':category', $category, PDO::PARAM_STR); 
		$stpdo->bindColumn(1, $id);
		$stpdo->execute(); 
		$rows = $stpdo->fetchAll(PDO::FETCH_OBJ);
		if (count($rows) == count($authors))
			return $rows[0]->id;
		else
			return 0;
	}
	
	public function getBasicData($limit = 20, $orderBy = "views", $fresh = false){
		# get all the basic data of some books
		$database = self::$database;
		$cache = self::$cache;
		$query = $this->queryBasic;
				
		if (!$database->sanitize($orderBy)){
			return null;
		}
		$query = str_replace("__order__", $orderBy, $query);	
		$cacheCheck = $this->cacheCheck($query, $fresh);
		if ($cacheCheck[0] != null){return $cacheCheck[0];}
		$stpdo = $database->getStpdo($query);
		$stpdo->bindParam(':limit', $limit, PDO::PARAM_INT); 
		$stpdo->bindColumn(1, $id); $stpdo->bindColumn(2, $title); $stpdo->bindColumn(3, $views);
		$stpdo->bindColumn(4, $pubblicationData); $stpdo->bindColumn(5, $coverExtension);
		$stpdo->execute(); 

		$rows = $stpdo->fetchAll(PDO::FETCH_OBJ);
		if ($rows){
			# if we retrieve less results than what we expected, we have a "no limits" query, so there's 
			# no reason to bound the query to the limit given.
			if (count($rows) == $limit){
				$this->cacheInsert($rows, $cacheCheck[1], $limit);
			}else{
				$this->cacheInsert($rows, $cacheCheck[1]);
			}
		}
		return $rows;
	}
	
	public function getView($id, $fresh = true){
		# important function, we may have problems / errors if we use cache here. So disable it
		# as default value. Get a single view (used to increment the visits)
		$queryViews = $this->queryBasic;
		$database = self::$database;
		$cache = self::$cache;
		$query = "SELECT views FROM books WHERE id = :id;";

		$res = $this->queryCache($query, $parameters = array("id" => $id));
		$queryCacheRes = $res[0]; $queryCache = $res[1];

		if (!$fresh){
			# have we have already done this query? Yes? Return it
			if ($queryCacheRes){
				return $cache[$queryCache]["data"];
			# we haven't? well, see if we have done the views query and if
			# inside it there is the value that we need
			}else{
				$res = $this->queryCache($this->queryBasic, array("limit" => 1));
				$queryCacheResViews = $res[0]; $queryCacheViews = $res[1];
				# if the query has been done, check the results 
				if ($queryCacheResViews){
					foreach($cache[$queryCacheViews]["data"] as $viewObj){
						if ($viewObj->id == $id){
							$this->cacheInsert($viewObj->id, $queryCache);
							return $viewObj->views;
						}
					}
				}
			}
		}
		# if where here means that we haven't returned yet, so it's correct
		$stpdo = $database->getStpdo($query);
		$stpdo->bindParam(':id', $id, PDO::PARAM_INT); 
		$stpdo->bindColumn(1, $views);
		$stpdo->execute(); 

		$row = $stpdo->fetch(PDO::FETCH_OBJ);
		if ($row){
			$this->cacheInsert($row->views, $queryCache);
			return $row->views;
		}
		return null;
	}
	
	public function getBook($id, $fresh = true){
		# get a single book data
		$database = self::$database;
		$cache = self::$cache;
		$query = "SELECT * FROM books WHERE id = :id;";

		$res = $this->queryCache($query, $parameters = array("id" => $id));
		$queryCacheRes = $res[0]; $queryCache = $res[1];

		# have we have already done this query? Yes? Return it
		if (!$fresh and $queryCacheRes){
			return $cache[$queryCache]["data"];
		}
		# if where here means that we haven't returned yet, so it's correct
		$stpdo = $database->getStpdo($query);
		$stpdo->bindParam(':id', $id, PDO::PARAM_INT); 
		$stpdo->execute(); 

		$row = $stpdo->fetch(PDO::FETCH_OBJ);
		if ($row){
			$this->cacheInsert($row, $queryCache);
			return $row;
		}
		return null;
	}
	
	public function getImportantBookData($id, $fresh = true){
		# get a lot of data of a book, used in the page that shows the book
		$database = self::$database;
		$cache = self::$cache;

		$query = 'SELECT b.title, b.isbn, b.shortDescription, b.editor, b.coverExtension, c.content, CONCAT(a.name, " ", a.surname) as author FROM books b JOIN booksContents c ON b.id = c.bookId 
				  JOIN booksAuthors ba ON b.id = ba.bookId JOIN authors a ON ba.authorId = a.id WHERE b.id= :id;';

		$res = $this->queryCache($query, $parameters = array("id" => $id));
		$queryCacheRes = $res[0]; $queryCache = $res[1];

		# have we have already done this query? Yes? Return it
		if (!$fresh and $queryCacheRes){
			return $cache[$queryCache]["data"];
		}
		# if we are here means that we haven't returned yet, so it's correct
		$stpdo = $database->getStpdo($query);
		$stpdo->bindParam(':id', $id, PDO::PARAM_INT); 
		$stpdo->execute(); 

		$row = $stpdo->fetchAll(PDO::FETCH_OBJ);
		if ($row){
			# if we have more than one row means that we have multiple authors
			if (count($row) > 1){
				$baseRow = $row[0];
				$baseRow->authors = array($baseRow->author);
				unset($baseRow->author);
				foreach($row as $key => $singleRow){
					if ($key != 0){
						$baseRow->authors[] = $singleRow->author;
					}
				}
				$baseRow->authors = implode(", ", $baseRow->authors);
				$this->cacheInsert($baseRow, $queryCache);
				return $baseRow;
			}
			$row[0]->authors = $row[0]->author;
			unset($row[0]->author);
			$this->cacheInsert($row[0], $queryCache);
			return $row[0];
		}
		return null;
	}
	
	public function viewsPlusOne($id){
		# add one to the number of views of a book
		$database = self::$database;
		$database->beginTransaction();
		$views = $this->getView($id);
		$database->execSecure("UPDATE books SET views = :views where id = :id;", array(":id" => $id, ":views" => $views+1));
		$database->commit();
	}
	
	public function bookInsert($bookTitle, $bookDescription, $category, $bookContent, $userId, $coverExtension, $isbn = NULL, $authorId = NULL,
		$authorName = NULL, $authorSurname = NULL, $editorName = NULL, $editorAddress = NULL, $editorPhoneNumber = NULL, $editorEmail = NULL){
		# book insertion
		$database = self::$database;
		return $database->execSecure("call bookInsert(:editorName, :editorAddress, :editorPhoneNumber, :editorEmail, :userId, 
		:authorId, :authorName, :authorSurname, :isbn, :bookTitle, :bookDescription, :category, :bookContent, :coverExtension, @o);", 
		array(":editorName" => $editorName, ":editorAddress" => $editorAddress, ":editorPhoneNumber" => $editorPhoneNumber, 
		":editorEmail" => $editorEmail, ":userId" => $userId, ":authorId" => $authorId, ":authorName" => $authorName, ":authorSurname" => $authorSurname, 
		":isbn" => $isbn, ":bookTitle" => $bookTitle, ":bookDescription" => $bookDescription, ":category" => $category, ":bookContent" => $bookContent,
		":coverExtension" => $coverExtension));
	}

	public function __destruct() {
		parent::__destruct();
	}
};

#$b = new Book();
#print_r($b->exists("Il codice da Perdi", "gialli", "Filippo De Pretto, Dan Petterson"));

?>
